import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.neighbors import LocalOutlierFactor
from imblearn.over_sampling import SMOTE
from collections import Counter
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn import svm
from sklearn.metrics import confusion_matrix, classification_report
from yellowbrick.classifier import ConfusionMatrix
from yellowbrick.classifier import ClassPredictionError
from yellowbrick.classifier import ROCAUC
from yellowbrick.style import set_palette
import SimpleSVC
import os
# 加载检查数据
print("加载检查数据:")
df= pd.read_csv("star_classification.csv")
print(df.head())
print(df.info())
print(df["class"].value_counts())
# 共有三类，星系、类星体和恒星
df["class"]=[0 if i == "GALAXY" else 1 if i == "STAR" else 2 for i in df["class"]]
# 类别数量可视化
sns.countplot(df["class"], palette="Set3")
plt.title("Class ",fontsize=10)
plt.savefig('类别数量可视化.png')
plt.show()

# 使用LOF算法检测异常值
clf = LocalOutlierFactor()
y_pred = clf.fit_predict(df)
x_score = clf.negative_outlier_factor_
outlier_score = pd.DataFrame()
outlier_score["score"] = x_score
#threshold
threshold2 = -1.5
filtre2 = outlier_score["score"] < threshold2
outlier_index = outlier_score[filtre2].index.tolist()
df.drop(outlier_index, inplace=True)

# 特征选择
f,ax = plt.subplots(figsize=(12,8))
sns.heatmap(df.corr(), cmap="PuBu", annot=True, linewidths=0.5, fmt= '.2f',ax=ax)
plt.savefig('特征关联性热力图.png')
plt.show()

corr = df.corr()
print(corr["class"].sort_values())
df = df.drop(['obj_ID','alpha','delta','run_ID','rerun_ID','cam_col','field_ID','fiber_ID'], axis = 1)

# 用SMOTE处理不平衡数据
x = df.drop(['class'], axis = 1)
y = df.loc[:,'class'].values
sm = SMOTE(random_state=42)
print('Original dataset shape %s' % Counter(y))
x, y = sm.fit_resample(x, y)
print('Resampled dataset shape %s' % Counter(y))

sns.countplot(y, palette='Set3')
plt.title("Class ",fontsize=10)
plt.savefig('类别数量可视化_处理不平衡之后.png')
plt.show()

# 数据缩放
scaler = StandardScaler()
scaler.fit(x)
x = scaler.transform(x)

# 数据划分
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size = 0.33, random_state = 42)

# 使用核方法的SVM分类器
svm_clf_rbf = svm.SVC(kernel='rbf', C=1, random_state=0)
svm_clf_rbf.fit(x_train,y_train)
predicted_rbf = svm_clf_rbf.predict(x_test)
score_rbf = svm_clf_rbf.score(x_test, y_test)
svm_score_rbf = np.mean(score_rbf)

# 输出支持向量
print('Support vectors for rbf kernel:', svm_clf_rbf.support_vectors_)

# 使用线性模型的SVM分类器
svm_clf_linear = svm.SVC(kernel='linear', C=1, random_state=0)
svm_clf_linear.fit(x_train,y_train)
predicted_linear = svm_clf_linear.predict(x_test)
score_linear = svm_clf_linear.score(x_test, y_test)
svm_score_linear = np.mean(score_linear)

# 输出支持向量
print('Support vectors for linear kernel:', svm_clf_linear.support_vectors_)

# 使用自己的SVM分类器
svm_clf_mine = SimpleSVC.SimpleSVC(C=1)
svm_clf_mine.fit(x_train,y_train)
predicted_mine = svm_clf_mine.predict(x_test)
score_linear = svm_clf_mine.score(x_test, y_test)
svm_score_mine = np.mean(score_linear)

# 输出支持向量
print('Support vectors for linear kernel:', svm_clf_mine.support_vectors_)


# 输出准确率
print('Accuracy for rbf kernel: %.3f' % (svm_score_rbf))
print('Accuracy for linear kernel: %.3f' % (svm_score_linear))
print('Accuracy for MySVM: %.3f' % (svm_score_mine))


# 可视化
plt.figure(figsize=(12, 6))
plt.subplot(121)
plt.scatter(x_train[:, 0], x_train[:, 1], c=y_train, cmap='coolwarm')
plt.scatter(svm_clf_rbf.support_vectors_[:, 0], svm_clf_rbf.support_vectors_[:, 1], s=100, facecolors='none', edgecolors='k')
plt.title('rbf kernel')

plt.subplot(122)
plt.scatter(x_train[:, 0], x_train[:, 1], c=y_train, cmap='coolwarm')
plt.scatter(svm_clf_linear.support_vectors_[:, 0], svm_clf_linear.support_vectors_[:, 1], s=100, facecolors='none', edgecolors='k')
plt.title('linear kernel')

plt.show()

classes = ['GALAXY','STAR','QSO']
# 混淆矩阵
svm_cm = ConfusionMatrix(svm_clf_rbf, classes=classes, cmap='GnBu')

svm_cm.fit(x_train, y_train)
svm_cm.score(x_test, y_test)
svm_cm.show()
# svm_cm.savefig('混淆矩阵.png')

print(classification_report(y_test, predicted_rbf))

# 绘制ROC曲线
visualizer = ROCAUC(svm_clf_rbf, classes=classes)

set_palette('bold')

visualizer.fit(x_train, y_train)        # Fit the training data to the visualizer
visualizer.score(x_test, y_test)        # Evaluate the model on the test data
visualizer.show()                       # Finalize and render the figure
# visualizer.savefig('ROC.png')
# 类预测结果
visualizer = ClassPredictionError(svm_clf_rbf, classes=classes)

set_palette('pastel')

visualizer.fit(x_train, y_train)        # Fit the training data to the visualizer
visualizer.score(x_test, y_test)        # Evaluate the model on the test data
visualizer.show()                       # Draw visualization
# visualizer.savefig('结果可视化.png')